package com.cly.base.service;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cly.base.dto.BasePageParam;
import com.cly.base.entity.BaseEntity;
import com.cly.result.JsonRequest;
import com.cly.result.exception.ServiceException;
import com.cly.result.exenum.RequestException;
import com.cly.utils.QueryUtils;
import lombok.SneakyThrows;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Objects;

/**
 * 基础业务层实现
 *
 * @author by 春风能解释
 * <p>
 * 2024/8/29
 */
public class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseEntity, SD, QD, UD, V, IT extends Serializable> extends ServiceImpl<M, T> implements IBaseService<T, SD, QD, UD, V, IT> {
    /**
     * 查询条件的Class
     */
    private Class<QD> queryClass;

    /**
     * 新增的Class
     */
    private Class<SD> saveClass;

    /**
     * 修改的Class
     */
    private Class<UD> updateClass;
    /**
     * 展示的Class
     */
    private Class<V> voClass;

    /**
     * 基础的列表查询逻辑
     *
     * @param queryDto 查询条件
     * @return JSON
     */
    @Override
    public JsonRequest<List<V>> baseList(QD queryDto) {
        List<T> dataList;
        if (Objects.isNull(queryDto)) {
            dataList = baseMapper.selectList(null);
            return JsonRequest.success(BeanUtil.copyToList(dataList, getVoClass()));
        }
        T query = BeanUtil.copyProperties(queryDto, getEntityClass());
        QueryChainWrapper<T> queryChainWrapper = QueryUtils.wrapperQueryBuilder(query, getEntityClass());
        if (queryChainWrapper == null) {
            throw new ServiceException(RequestException.SELECT_ERROR);
        }
        return JsonRequest.success(BeanUtil.copyToList(queryChainWrapper.list(), getVoClass()));
    }

    /**
     * 基础的分页查询逻辑
     *
     * @param queryDto 查询条件
     * @return JSON
     */
    @Override
    public JsonRequest<List<V>> basePage(BasePageParam<QD> queryDto) {
        return null;
    }


    /**
     * 基础的新增逻辑
     *
     * @param saveDto 新增条件
     * @return JSON
     */
    @Override
    public JsonRequest<Integer> baseAdd(SD saveDto) {
        T data = BeanUtil.copyProperties(saveDto, getEntityClass());
        int column = baseMapper.insert(data);
        if (column < 1) {
            return JsonRequest.error(RequestException.INSERT_ERROR);
        }
        return JsonRequest.success(column);
    }

    /**
     * 基础的修改逻辑
     *
     * @param updateDto 修改条件
     * @return JSON
     */
    @Override
    public JsonRequest<Integer> baseUpdate(UD updateDto) {
        IT idValue = getIdValue(updateDto);
        if (idValue == null) {
            return JsonRequest.error(RequestException.UPDATE_ERROR);
        }
        T data = baseMapper.selectById(idValue);
        if (Objects.isNull(data)) {
            return JsonRequest.error(RequestException.NOT_FOUND);
        }
        T newData = BeanUtil.copyProperties(updateDto, getEntityClass());
        int column = baseMapper.updateById(newData);
        if (column < 1) {
            return JsonRequest.error(RequestException.UPDATE_ERROR);
        }
        return JsonRequest.success(column);
    }

    /**
     * 基础的删除逻辑
     *
     * @param ids 待删除的id
     * @return JSON
     */
    @Override
    public JsonRequest<Integer> baseDelete(List<IT> ids) {
        List<T> list = baseMapper.selectBatchIds(ids);
        if (list.size() != ids.size()) {
            throw new ServiceException(RequestException.NOT_FOUND);
        }
        int column = baseMapper.deleteByIds(ids);
        if (column < 1) {
            return JsonRequest.error(RequestException.DELETE_ERROR);
        }
        return JsonRequest.success(column);
    }

    /**
     * 获取查询条件的Class
     *
     * @return Class
     */
    protected Class<QD> getQueryDtoClass() {
        if (this.queryClass == null) {
            this.queryClass = (Class<QD>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }
        return this.queryClass;
    }

    /**
     * 获取新增的Class
     *
     * @return Class
     */
    protected Class<SD> getSaveDtoClass() {
        if (this.saveClass == null) {
            this.saveClass = (Class<SD>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }
        return this.saveClass;
    }

    /**
     * 获取修改的Class
     *
     * @return Class
     */
    protected Class<UD> getUpdateDtoClass() {
        if (this.updateClass == null) {
            this.updateClass = (Class<UD>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }
        return this.updateClass;
    }

    /**
     * 获取修改的Class
     *
     * @return Class
     */
    protected Class<V> getVoClass() {
        if (this.voClass == null) {
            this.voClass = (Class<V>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }
        return this.voClass;
    }

    /**
     * 得到主键值
     *
     * @param updateDto 修改条件
     * @return 主键值
     */
    @SneakyThrows
    protected IT getIdValue(UD updateDto) {
        // 判断实体类和修改条件是否为空
        if (getEntityClass() == null || getUpdateDtoClass() == null) {
            return null;
        }
        // 获取主键的名称
        for (Field field : getEntityClass().getFields()) {
            if (field.getAnnotation(TableId.class) != null) {
                return (IT) field.get(updateDto);
            }
        }
        return null;
    }
}
